package com.thb.pay.manage.web.sys;

import com.thb.pay.api.sys.SysUserServiceApi;
import com.thb.pay.core.annotation.OperationLog;
import com.thb.pay.core.cache.EhcacheUtils;
import com.thb.pay.core.enums.ExceptionEnum;
import com.thb.pay.core.exception.RRException;
import com.thb.pay.core.jwt.JwtUtils;
import com.thb.pay.core.utils.Constant;
import com.thb.pay.core.utils.R;
import com.thb.pay.manage.comm.controller.BaseController;
import com.thb.pay.vo.req.LoginReq;
import com.thb.pay.vo.resp.SysUserVo;
import com.xiaoleilu.hutool.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;

@Slf4j
@RestController
@RequestMapping("/api")
public class LoginController extends BaseController {

    private static Integer CACHE_MANAGE_USER_TIME_KEY = 60 * 60 * 24;//缓存用户时间 一天

    private static Integer CACHE_LOCK_TIME = 60 * 60;// 锁住一个小时 错误三次锁

    private static Integer DEFAULT_COUNT = 1;

    private static Integer MAX_ERROR_USER_COUNT = 3;//登入最大错误次数

    private static String LOCKED_MANAGE_USER_KEY = "locked:manage:user:%s";


    private static String CACHE_MANAGE_NAME = "cacheManageUser";

    private static String CACHE_MANAGE_USER_KEY = "manage:user:%s";

    private static String CACHE_MANAGE_USE_ERROR_COUNT_KEY = "manage:user:error:count:%s";//用户错误次数

    @Autowired
    private SysUserServiceApi sysUserServiceApi;

    @Autowired
    private JwtUtils jwtUtils;

    /**
     * 登录
     */
    @RequestMapping(value = "/auth")
    @OperationLog(value = "登录")
    public R auth(@RequestBody @Valid LoginReq loginReq) {
        Object userErrorCount = EhcacheUtils.getInstance().get(CACHE_MANAGE_NAME, String.format(CACHE_MANAGE_USE_ERROR_COUNT_KEY, loginReq.getUsername()));
        if (userErrorCount != null) {
            if (Integer.valueOf(userErrorCount + "") >= MAX_ERROR_USER_COUNT) {
                throw RRException.build(ExceptionEnum.LOCK_USERNAME);//锁住用户
            }
        }
        SysUserVo sysUserVo = sysUserServiceApi.getByUserName(loginReq.getUsername());
        if (sysUserVo == null) {
            if (log.isDebugEnabled()) {
                log.debug("manage.username:{},is.not.exist.", loginReq.getUsername());
            }
            throw RRException.build(ExceptionEnum.USERNAME_OR_PASSWORD_INCORRECT);
        }
        //验证密码
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        boolean is_password = encoder.matches(sysUserVo.getPassword(), loginReq.getPassword());
        if (!is_password) {
            if (log.isDebugEnabled()) {
                log.debug("manage.username:{},password:{},incorrect.{}", loginReq.getUsername(), loginReq.getPassword());
            }
            Integer targetUserErrorCount = userErrorCount == null ? 1 : (Integer.valueOf(userErrorCount + "") + 1);
            EhcacheUtils.getInstance().set(CACHE_MANAGE_NAME, CACHE_MANAGE_USE_ERROR_COUNT_KEY, targetUserErrorCount, CACHE_MANAGE_USER_TIME_KEY);//缓存错误时间
            throw RRException.build(ExceptionEnum.USERNAME_OR_PASSWORD_INCORRECT);
        }


        EhcacheUtils.getInstance().remove(CACHE_MANAGE_NAME, String.format(CACHE_MANAGE_USE_ERROR_COUNT_KEY, loginReq.getUsername()));
        String accessToken = jwtUtils.generateToken(sysUserVo.getId());
        sysUserVo.setAccessToken(accessToken);
        EhcacheUtils.getInstance().set(String.format(Constant.ACCESS_TOKEN, accessToken), sysUserVo, Constant.EXPIRE_ACCESS_TOKEN_TIME);

        return R.okData(sysUserVo);
    }

    /**
     * 获取验证码
     */
    @RequestMapping(value = "/authCode")
    public void generateAuthCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String randomString = RandomUtil.randomString(5);
        ImageIO.write(null, "JPEG", response.getOutputStream());
    }

}
